package cn.aifeix.basic.service.impl;

import cn.aifeix.basic.config.BussinessException;
import cn.aifeix.basic.constant.BaseConstant;
import cn.aifeix.basic.dto.EmailCodeDto;
import cn.aifeix.basic.dto.PhoneSmsCodeDto;
import cn.aifeix.basic.service.IVerifyCodeService;
import cn.aifeix.basic.util.EmailUtil;
import cn.aifeix.basic.util.StrUtils;
import cn.aifeix.basic.util.VerifyCodeUtils;
import cn.aifeix.user.domain.User;
import cn.aifeix.user.mapper.LogininfoMapper;
import cn.aifeix.user.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;
    /**
     * 图形验证码
     * @param uuidKey
     * @return
     */
    @Override
    public String getImageCode(String uuidKey) {
        // 生成随机数
        String random = StrUtils.getComplexRandomString(4);
        // 存入redis
        redisTemplate.opsForValue().set(uuidKey, random, 3, TimeUnit.MINUTES);
        // 将随机数生成图形验证码转成base64发给前端
        return VerifyCodeUtils.VerifyCode(100, 35, random);
    }

    /**
     * 手机验证码
     * @param dto
     */
    @Override
    public void smsCode(PhoneSmsCodeDto dto) {
        // 参数非空校验PhoneSmsCodeDto里已做
        // 手机号格式验证
        if (!Pattern.matches("^1[3|4|5|7|8][0-9]{9}$",dto.getPhone())){
            throw new BussinessException("手机号码格式错误！");
        }
        if ("register".equals(dto.getType())){
            // 判断为注册 需要图形验证码
            isImgageCode(dto);
            // 短信发送业务
            sendSmsCode(String.format(BaseConstant.VerfityCodeCons.REGISTER_SMSCODE_PHONE, dto.getPhone()));
        }else if ("binder".equals(dto.getType())){
            // 判断为绑定 直接进入短信发送流程
            sendSmsCode(String.format(BaseConstant.VerfityCodeCons.BINDER_SMSCODE_PHONE,dto.getPhone()));
        }
    }

    private void isImgageCode(PhoneSmsCodeDto dto) {
        // 校验图形验证码是否正确
        // 获取redis中的uuid
        String imageCode = (String) redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if (StringUtils.isBlank(imageCode) || !imageCode.equalsIgnoreCase(dto.getImageCodeValue())){
            throw new BussinessException("图形验证码错误！");
        }
        // 当前手机号是否已经注册了
        User user = userMapper.findByPhone(dto.getPhone());
        if (null != user){
            throw new BussinessException("手机号已注册，请直接登录！");
        }
    }

    /**
     * 短信发送抽取
     * @param redisKey
     */
    private void sendSmsCode(String redisKey) {
        // 两次发送短信间隔是否大于60s redis中 key：register:smscode:phone  value：验证码:时间戳
        String redisSmsCode = (String) redisTemplate.opsForValue()
                .get(redisKey);
        String smsCode = "";
        if (StringUtils.isNotBlank(redisSmsCode)){
            // 不为空才做 60s校验  redisSmsCode 存的是 验证码:时间戳
            String[] split = redisSmsCode.split(":");
            smsCode = split[0];
            // 当前时间
            long newTime = System.currentTimeMillis();
            // reids中的时间
            long oldTime = Long.valueOf(split[1]);
            if (newTime - oldTime < 60 * 1000){
                throw new BussinessException("请稍后重试！");
            }
        }else {
            // 生成验证码
            smsCode = StrUtils.getRandomString(4);
        }
        log.info("验证码为：{}",smsCode);
        String redisValue = smsCode+":"+ System.currentTimeMillis();
        // 存入到reids
        redisTemplate.opsForValue().set(redisKey,redisValue,5,TimeUnit.MINUTES);
        // 发送短信
//        SendSmsUtil.send(dto.getPhone(),"你好：你的验证码为："+smsCode+"，5分钟内有效！");
    }

    /**
     * 邮箱验证码
     * @param dto
     */
    @Override
    public void emailCode(EmailCodeDto dto) {
        // 参数非空校验PhoneSmsCodeDto里已做
        // 邮箱格式验证
        if (!Pattern.matches("^([a-z0-9A-Z]+[-|_|\\\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$",dto.getEmail())){
            throw new BussinessException("邮箱格式错误！");
        }
        // 校验图形验证码是否正确
        // 获取redis中的uuid
        String imageCode = (String) redisTemplate.opsForValue().get(dto.getImageCodeKey());
        if (StringUtils.isBlank(imageCode) || !imageCode.equalsIgnoreCase(dto.getImageCodeValue())){
            throw new BussinessException("图形验证码错误！");
        }
        // 当前邮箱是否已经注册了
        User user = userMapper.findByEmail(dto.getEmail());
        if (null != user){
            throw new BussinessException("邮箱已注册，请直接登录！");
        }
        // 两次发送短信间隔是否大于60s redis中 key：register:smscode:email  value：验证码:时间戳
        String redisEmailCode = (String) redisTemplate.opsForValue()
                .get(String.format(BaseConstant.VerfityCodeCons.REGISTER_EMAILCODE_EMAIL, dto.getEmail()));
        String emailCode = "";
        if (StringUtils.isNotBlank(redisEmailCode)){
            String[] split = redisEmailCode.split(":");
            emailCode = split[0];
            // 当前时间
            long newTime = System.currentTimeMillis();
            // reids中的时间
            long oldTime = Long.valueOf(split[1]);
            if (newTime - oldTime < 60 * 1000){
                throw new BussinessException("稍后重试！");
            }
        }else {
            // 生成验证码
            emailCode = StrUtils.getRandomString(4);
        }
        log.info("验证码为：{}",emailCode);
        String redisValue = emailCode+":"+ System.currentTimeMillis();
        // 存入到reids
        redisTemplate.opsForValue().set(String.format(BaseConstant.VerfityCodeCons.REGISTER_EMAILCODE_EMAIL,dto.getEmail()),
                redisValue,5,TimeUnit.MINUTES);
        // 发送邮箱
        EmailUtil.sendEmail("1048977284@qq.com","宠物之家注册验证", "你好：你的验证码为："+emailCode+"，5分钟内有效！", dto.getEmail());
    }
}
